package com.hup.minicontroller.client.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;

import androidx.annotation.Nullable;

import com.hup.minicontroller.client.R;

import lombok.Setter;

/**
 * 连接成功后,显示的按钮悬浮窗,用于:
 * .打开/关闭配置面板
 * .展示[back,home,app]按钮
 *
 * @author hugan
 * @date 2021/5/6
 */
public class ButtonFloaterView extends RelativeLayout {
    private static final String TAG = ButtonFloaterView.class.getSimpleName();
    private static final int LAYOUT_ID = R.layout.button_floater_view;

    public View btnTrigger;
    public View btnBack, btnHome, btnApp;
    @Setter
    private DraggedCallback draggedCallback;
    /**
     * 启动app时得到的上次保存的坐标配置(百分比),只应用一次后就置空,因为用户拖拽后不会更新这两个属性
     */
    private Float buttonFloaterX, buttonFloaterY;

    public ButtonFloaterView(Context context) {
        this(context, null);
    }

    public ButtonFloaterView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ButtonFloaterView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public ButtonFloaterView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(LAYOUT_ID, this);
        btnTrigger = findViewById(R.id.btnTrigger);
        btnBack = findViewById(R.id.btnBack);
        btnHome = findViewById(R.id.btnHome);
        btnApp = findViewById(R.id.btnApp);
        setWillNotDraw(false);
        //监听
        DragViewListener dragViewListener = new DragViewListener();
        btnTrigger.setOnTouchListener(dragViewListener);
        btnTrigger.setOnLongClickListener(dragViewListener);
    }

    /**
     * 切换功能按钮展示状态,关键是处理展示按钮时,修正悬浮窗的位置
     */
    public void switchFunctionButton(boolean isShow) {
        btnBack.setVisibility(isShow ? VISIBLE : GONE);
        btnHome.setVisibility(isShow ? VISIBLE : GONE);
        btnApp.setVisibility(isShow ? VISIBLE : GONE);
        if (isShow) {
            //展示时组件尺寸是异步更新的
            postDelayed(() -> {
                View parent = (View) getParent();
                if (getX() + getWidth() > parent.getWidth()) {
                    setX(parent.getWidth() - getWidth());
                }
            }, 100);
        }
    }

    /**
     * 应用配置中的坐标,注意很坑;
     * .Activity启动时或onResume时,不能直接setXY,因为此时view和view.parent都未初始化完成,此时会有下面异常:
     * .....view或parent.getWidth结果是0
     * .....view.setY传入的数值要是负数(应该和xml中layout_alignParentBottom有关)
     * .正确的应用配置的方法是,在 onLayout中应用坐标
     */
    public void setLocationPercent(float buttonFloaterX, float buttonFloaterY) {
        Log.i(TAG, "setLocationPercent: 应用buttonFloater坐标:" + buttonFloaterX + "," + buttonFloaterY);
        this.buttonFloaterX = buttonFloaterX;
        this.buttonFloaterY = buttonFloaterY;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if (changed && buttonFloaterX != null) {
            View parent = (View) getParent();
//            Log.i(TAG, "onLayout: " + parent.getWidth() + ", " + getWidth() + ", " + changed);
            float newX = buttonFloaterX * parent.getWidth();
            float newY = buttonFloaterY * parent.getHeight();
            float maxX = parent.getWidth() - getWidth();
            float maxY = parent.getHeight() - getHeight();
            if (newX < 0) newX = 0;
            else if (newX > maxX) newX = maxX;
            if (newY < 0) newY = 0;
            else if (newY > maxY) newY = maxY;
            setX(newX);
            setY(newY);
            buttonFloaterX = null;
            buttonFloaterY = null;
        }
    }

    /**
     * 实现长按拖拽view的监听
     */
    private class DragViewListener implements OnTouchListener, OnLongClickListener {
        private boolean isLongPressed, isDragging;
        private int lastXOnScreen, lastYOnScreen;
        /**
         * 开始拖拽时的事件坐标(相对于屏幕)
         */
        private int dragX0, dragY0;
        /**
         * 开始拖拽时的view坐标,允许拖拽的最大坐标
         */
        private float viewX0, viewY0, maxDragX, maxDragY;

        @Override
        public boolean onLongClick(View v) {
//            Log.i(TAG, "onLongClick: ");
            isLongPressed = true;
            return true;//返回true有系统震动效果
        }

        /**
         * @return 返回true代表已处理事件, 会屏蔽后续的监听(如长按事件)
         */
        @Override
        @SuppressLint("ClickableViewAccessibility")
        public boolean onTouch(View v, MotionEvent e) {
            int xOnScreen = (int) e.getRawX();
            int yOnScreen = (int) e.getRawY();
            switch (e.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    Log.d(TAG, "onTouch: ACTION_DOWN");
                    isLongPressed = false;
                    isDragging = false;
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (Math.abs(lastXOnScreen - xOnScreen) < 2 && Math.abs(lastYOnScreen - yOnScreen) < 2)
                        return false;//不更新last坐标
                    if (!isLongPressed) break;
                    if (!isDragging) {
                        //长按后首次move
                        onStartDrag(xOnScreen, yOnScreen);
                        break;
                    }
                    onDragging(xOnScreen, yOnScreen);
//                    Log.i(TAG, "onTouch: ACTION_MOVE");
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
//                    Log.i(TAG, "onTouch: ACTION_UP");
                    if (isDragging && draggedCallback != null) {
                        draggedCallback.onDragged();
                    }
                    isLongPressed = false;
                    isDragging = false;
                    break;
            }
            lastXOnScreen = xOnScreen;
            lastYOnScreen = yOnScreen;
            return isDragging;
        }

        /**
         * 开始拖拽前,记录和计算属性
         */
        private void onStartDrag(int xOnScreen, int yOnScreen) {
            isDragging = true;
            dragX0 = xOnScreen;
            dragY0 = yOnScreen;
            viewX0 = getX();
            viewY0 = getY();
            int viewWidth = getWidth();
            int viewHeight = getHeight();
            int parentWidth = ((View) getParent()).getWidth();
            int parentHeight = ((View) getParent()).getHeight();
            maxDragX = parentWidth - viewWidth;
            maxDragY = parentHeight - viewHeight;
        }

        /**
         * 拖拽view
         */
        private void onDragging(int xOnScreen, int yOnScreen) {
            float newX = viewX0 + (xOnScreen - dragX0);
            float newY = viewY0 + (yOnScreen - dragY0);
            if (newX < 0) newX = 0;
            else if (newX > maxDragX) newX = maxDragX;
            if (newY < 0) newY = 0;
            else if (newY > maxDragY) newY = maxDragY;
            setX(newX);
            setY(newY);
        }
    }

    /**
     * 拖拽结束的回调
     */
    public interface DraggedCallback {
        void onDragged();
    }

}
